#include "PreCompile.hpp"
#include "gpathext.hpp"
#include "Exception.hpp"

extern "C"
{
#include "g_path_ext.h"
}

namespace Glib
{
  Glib::ustring Path::get_relative_path(const Glib::ustring &full_path,
    const Glib::ustring &base_path)
  {
    gchar *ret = g_path_get_relative_path(full_path.c_str(),base_path.c_str());
    if(!ret)
      return "";

    Glib::ustring ret_ustr(ret);
    g_free(ret);
    return ret_ustr;
  }

  Glib::ustring Path::canonicalize_path(const Glib::ustring &path)
  {
    gchar *ret = g_path_canonicalize_path(path.c_str());
    if(!ret)
      throw BuildNG::Exception("Failed to canonicalize path \"" + path + "\".");
    Glib::ustring ret_ustr(ret);
    g_free(ret);
    return ret_ustr;
  }

  Glib::ustring Path::canonicalize_path(const Glib::ustring &path,int flags)
  {
    gchar *ret = g_path_canonicalize_path_full(path.c_str(),flags);
    Glib::ustring ret_ustr(ret);
    g_free(ret);
    return ret_ustr;
  }

  std::vector<Glib::ustring> Path::split_into_elements(const Glib::ustring &full)
  {
    GPtrArray *as_cstr_array = g_path_split_into_elements(full.c_str());

    try
    {
      std::vector<Glib::ustring> ret;
      ret.reserve(as_cstr_array->len);
      for(int i = 0;i < (int)as_cstr_array->len;i++)
      {
        Glib::ustring as_ustr((gchar*)g_ptr_array_index(as_cstr_array,i));
        ret.push_back(as_ustr);

        g_free(g_ptr_array_index(as_cstr_array,i));
        g_ptr_array_index(as_cstr_array,i) = 0;
      }

      g_ptr_array_free(as_cstr_array,TRUE);
      as_cstr_array = 0;

      return ret;
    }
    catch(...)
    {
      if(as_cstr_array)
      {
        for(int i = 0;i < (int)as_cstr_array->len;i++)
        {
          g_free(g_ptr_array_index(as_cstr_array,i));
        }
        g_ptr_array_free(as_cstr_array,TRUE);
      }

      throw;
    }
  }

  Glib::ustring Path::get_absolute_path(const Glib::ustring &path)
  {
    return get_absolute_path(path,Glib::get_current_dir());
  }

  Glib::ustring Path::get_absolute_path(const Glib::ustring &path,const Glib::ustring &base_dir)
  {
    if(Glib::path_is_absolute(path))
      return path;
    else
    {
      Glib::ustring combined = Glib::build_filename(base_dir,path);
      return canonicalize_path(combined);
    }
  }
}
